﻿using System.Collections.Generic;
using System.Data;
using System.Text;

using SqlExecHelper.Cache;
using SqlExecHelper.Column;
using SqlExecHelper.TempTable;

namespace SqlExecHelper.Query
{
        internal class TempTableQuery : BatchTempTable, ISqlBasic, IBatchQuery
        {
                public TempTableQuery (string table, RunParam param, IDAL myDAL) : base (table, param, "t", myDAL)
                {
                }
                private string _OrderBy = null;

                private string[] _Group = null;

                private ISqlWhere[] _Having = null;

                private int _TopNum = -1;

                private ISqlWhere[] _Where = null;

                private SqlColumn[] _Column = null;
                private int _Skip = 0;
                private int _Size = 0;
                private bool _IsPaging = false;
                private bool _IsCount = true;

                private void _InitFoot (StringBuilder sql, List<IDataParameter> param)
                {
                        if (this._Skip != 0)
                        {
                                SqlTools.InitPaging (sql, this._OrderBy, this._Skip, this._Size, this.Config, param);
                        }
                        else
                        {
                                SqlTools.InitGroup (sql, this._OrderBy, this._Group, this._Having, this.Config, param);
                        }
                }
                private string _GetSqlBody (List<IDataParameter> param)
                {
                        StringBuilder main = new StringBuilder (256);
                        main.AppendFormat (" from {0},{1} where ", this.FullTableName, this._TempTable.TableName);
                        SqlTools.InitColumn (this._TempTable, main, this.Config);
                        if (!this._Where.IsNull ())
                        {
                                SqlTools.AppendWhere (main, this.Config, this._Where, param);
                        }
                        return main.ToString ();
                }
                private StringBuilder _GeneratePagingSql (out IDataParameter[] param)
                {
                        List<IDataParameter> list = new List<IDataParameter> ();
                        string main = this._GetSqlBody (list);
                        StringBuilder sql = new StringBuilder ("select ", ( main.Length * 2 ) + 256);
                        SqlTools.InitColumn (sql, this._Column, this.Config);
                        sql.Append (main);
                        if (this._IsCount)
                        {
                                SqlTools.InitPaging (sql, this._OrderBy, this._Skip, this._Size, this._Column[0].Name, this.Config, main, list);
                        }
                        else
                        {
                                SqlTools.InitPaging (sql, this._OrderBy, this._Skip, this._Size, this.Config, list);
                        }
                        param = list.ToArray ();
                        return sql;
                }
                public StringBuilder GenerateSql (out IDataParameter[] param)
                {
                        if (this._IsPaging)
                        {
                                return this._GeneratePagingSql (out param);
                        }
                        else
                        {
                                StringBuilder sql = new StringBuilder ("select ", 512);
                                SqlTools.InitHead (sql, this._TopNum);
                                SqlTools.InitColumn (sql, this._Column, this.Config);
                                List<IDataParameter> list = new List<IDataParameter> ();
                                sql.Append (this._GetSqlBody (list));
                                this._InitFoot (sql, list);
                                param = list.ToArray ();
                                return sql;
                        }
                }
                private T[] _Query<T> (out long count)
                {
                        if (!this._TempTable.Save ())
                        {
                                count = 0;
                                return null;
                        }
                        return SqlHelper.Query<T> (this, this._MyDAL, out count);
                }
                private T _ExecuteScalar<T> ()
                {
                        if (!this._TempTable.Save ())
                        {
                                return default;
                        }
                        return SqlHelper.ExecuteScalar<T> (this, this._MyDAL);
                }
                private T[] _GetTable<T> ()
                {
                        if (!this._TempTable.Save ())
                        {
                                return null;
                        }
                        return SqlHelper.GetTable<T> (this, this._MyDAL);
                }
                private T _GetRow<T> ()
                {
                        if (!this._TempTable.Save ())
                        {
                                return default;
                        }
                        return SqlHelper.GetRow<T> (this, this._MyDAL);
                }
                #region 分组查询

                public T[] GroupColumn<T> (string group, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Column = new SqlColumn[] {
                                new SqlColumn(group),
                        };
                        this._Group = new string[] { group };
                        return this._GetTable<T> ();
                }
                public T[] GroupTable<T> (string group, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._Group = new string[] { group };
                        return this._GetTable<T> ();
                }
                public T Group<T> (string group, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._Group = new string[] { group };
                        return this._GetRow<T> ();
                }
                public T[] GroupTable<T> (string group, string sortBy, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._OrderBy = sortBy;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._Group = new string[] { group };
                        return this._GetTable<T> ();
                }
                public T Group<T> (string[] group, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._Group = group;
                        return this._GetRow<T> ();
                }
                public T[] GroupTable<T> (string[] group, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._Group = group;
                        return this._GetTable<T> ();
                }
                public T[] GroupTable<T> (string[] group, string sortBy, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._OrderBy = sortBy;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._Group = group;
                        return this._GetTable<T> ();
                }
                public T[] GroupColumn<T> (string group, int index, int size, out long count, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Column = new SqlColumn[] {
                                new SqlColumn(group),
                        };
                        this._Group = new string[] { group };
                        this._OrderBy = group;
                        this._IsPaging = true;
                        this._Skip = ( index - 1 ) * size;
                        this._Size = size;
                        return this._Query<T> (out count);
                }
                #endregion

                #region 分组查询(Group by having)
                public T[] GroupColumn<T> (string group, ISqlWhere[] having, params ISqlWhere[] where)
                {
                        this._Having = having;
                        this._Where = where;
                        this._Column = new SqlColumn[] {
                                new SqlColumn(group),
                        };
                        this._Group = new string[] { group };
                        return this._GetTable<T> ();
                }
                public T[] GroupTable<T> (string group, ISqlWhere[] having, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Having = having;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._Group = new string[] { group };
                        return this._GetTable<T> ();
                }
                public T Group<T> (string group, ISqlWhere[] having, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Having = having;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._Group = new string[] { group };
                        return this._GetRow<T> ();
                }
                public T[] GroupTable<T> (string group, string orderBy, ISqlWhere[] having, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Having = having;
                        this._OrderBy = orderBy;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._Group = new string[] { group };
                        return this._GetTable<T> ();
                }


                public T[] GroupTable<T> (string[] groups, ISqlWhere[] having, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Having = having;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._Group = groups;
                        return this._GetTable<T> ();
                }
                public T[] GroupTable<T> (string[] groups, string orderBy, ISqlWhere[] having, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Having = having;
                        this._OrderBy = orderBy;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._Group = groups;
                        return this._GetTable<T> ();
                }
                #endregion

                #region 单列函数查询(count,sum等)
                public T ExecuteScalar<T> (string column, SqlFuncType funcType, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Column = new SqlColumn[]
                        {
                                new SqlColumn(column, funcType)
                        };
                        return this._ExecuteScalar<T> ();
                }
                public T ExecuteScalar<T> (string column, string funcType, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Column = new SqlColumn[]
                        {
                                new SqlColumn(column, null,funcType)
                        };
                        return this._ExecuteScalar<T> ();
                }
                #endregion

                #region 查询
                public T[] Query<T> (string column, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Column = new SqlColumn[]
                        {
                                new SqlColumn(column)
                        };
                        return this._GetTable<T> ();
                }
                public T[] Query<T> (params ISqlWhere[] where)
                {
                        return this.QueryBySort<T> (null, where);
                }
                #endregion

                #region 排序查询
                public T[] QueryBySort<T> (string orderBy, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._OrderBy = orderBy;
                        return this._GetTable<T> ();
                }
                #endregion

                #region 分页查询
                public T[] QueryByPaging<T> (string orderBy, int index, int size, out long count, params ISqlWhere[] where)
                {
                        this._Where = where;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._OrderBy = orderBy;
                        this._IsPaging = true;
                        this._Skip = ( index - 1 ) * size;
                        this._Size = size;
                        return this._Query<T> (out count);
                }

                public T[] QueryByPaging<T> (string orderBy, int index, int size, params ISqlWhere[] where)
                {
                        this._IsPaging = true;
                        this._IsCount = false;
                        this._Where = where;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._OrderBy = orderBy;
                        this._Skip = ( index - 1 ) * size;
                        this._Size = size;
                        return this._GetTable<T> ();
                }
                #endregion

                #region Top查询
                public T[] QueryByTop<T> (int topNum, params ISqlWhere[] where)
                {
                        return this.QueryByTop<T> (topNum, null, where);
                }
                public T[] QueryByTop<T> (int topNum, string orderBy, params ISqlWhere[] where)
                {
                        this._TopNum = topNum;
                        this._Where = where;
                        this._Column = ClassStructureCache.GetQueryColumn (typeof (T));
                        this._OrderBy = orderBy;
                        return this._GetTable<T> ();
                }
                #endregion
        }
}
